/*
  LEDCube 


*/

#include "LEDCube.h"
#include <Arduino.h>

#define LED(x,y) (x+8*y)
int leds[]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,0};

LEDCube::LEDCube(int data, int clock, int latch, int layer1, int layer2, int layer3, int layer4, int layer5, int layer6, int layer7, int layer8, int enablePin)
    : m_dataPin (data), 
      m_clockPin (clock), 
      m_latchPin (latch),
      m_enablePin (enablePin)
  {
    pinMode(data, OUTPUT);
    pinMode(clock,  OUTPUT);
    pinMode(latch, OUTPUT);
    pinMode(layer1, OUTPUT);
    pinMode(layer2, OUTPUT);
    pinMode(layer3, OUTPUT);
    pinMode(layer4, OUTPUT);
    pinMode(layer5, OUTPUT);
    pinMode(layer6, OUTPUT);
    pinMode(layer7, OUTPUT);
    pinMode(layer8, OUTPUT);

    clearAllLayers();
    layerPins[0] = layer1;
    layerPins[1] = layer2;
    layerPins[2] = layer3;
    layerPins[3] = layer4;
    layerPins[4] = layer5;
    layerPins[5] = layer6;
    layerPins[6] = layer7;
    layerPins[7] = layer8;

  }

void LEDCube::setLayerData(uint16_t data, uint8_t layerNum, uint8_t chip)
{
 layerData[layerNum][chip] = data;
}

void LEDCube::shiftOutAll(int layerDelay) {

    for (int layer=0; layer<8; layer++) {

        //Write a layer
        digitalWrite(m_latchPin,LOW);
        shiftOut64(layer);
        digitalWrite(m_enablePin, HIGH);
        disableLayers();
        //digitalWrite(m_latchPin,HIGH);
        digitalWrite(m_latchPin,LOW);
        enableLayer(layer);
        digitalWrite(m_enablePin,LOW);
        delay(layerDelay);
    }

}

void LEDCube::setXYZ(uint8_t x, uint8_t y, uint8_t z) {

  int chip=0;
  int light=0;
  int i = LED(x,y);
  light = i%(16);
  light++;
  chip = i>>4;
  layerData[z][chip] |= leds[light];
}

void LEDCube::clearAllLayers() {
    for (int i=0; i<8; i++) {
        clearLayer(i);
    }
}

void LEDCube::clearLayer(int layerNum) {
    for (int i =0; i<4; i++) {
        layerData[layerNum][i] = 0;

    }
}

void LEDCube::enableLayer(int layerNum) {

    digitalWrite(layerPins[layerNum],LOW);
}

void LEDCube::shiftOut64(uint8_t layerNum)
{

    
    digitalWrite(m_latchPin, LOW);


    for (int chp=3;chp>=0;chp--){
    shiftOut(m_dataPin, m_clockPin, MSBFIRST, layerData[layerNum][chp] >>8);   // send high byte
    shiftOut(m_dataPin, m_clockPin, MSBFIRST, layerData[layerNum][chp]);
    }
    //return the latch pin HIGH to update LED's
    digitalWrite(m_latchPin, HIGH);
    digitalWrite(m_latchPin, LOW);
            
                
}


void LEDCube::disableLayers() {
    for (int i =0; i<8; i++) {
        digitalWrite(layerPins[i],HIGH);
    }
}
